package com.fastwire.carriere.controller.impl;

import java.util.Date;
import java.util.List;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import com.fastwire.carriere.common.Messages;
import com.fastwire.carriere.common.constant.ScheduledTaskConstants;
import com.fastwire.carriere.common.exception.ResourceException;
import com.fastwire.carriere.common.util.DateUtil;
import com.fastwire.carriere.controller.SchedulerController;
import com.fastwire.carriere.dao.DAOException;
import com.fastwire.carriere.dao.DAOFactory;
import com.fastwire.carriere.dao.ScheduledTaskDao;
import com.fastwire.carriere.schedule.MultiTaskScheduler;
import com.fastwire.carriere.schedule.entity.ScheduledTask;
import com.fastwire.carriere.schedule.runnable.RadDiscoveryThread;
import com.fastwire.carriere.schedule.runnable.U2kDiscoveryThread;
import com.fastwire.carriere.schedule.runnable.U2kProvisionThread;
import com.fastwire.carriere.schedule.vo.ScheduledTaskVo;
import com.google.common.collect.Lists;

public class SchedularControllerImpl implements SchedulerController {

	/** The scheduled task dao. */
	private final ScheduledTaskDao scheduledTaskDao = DAOFactory.getInstance()
			.getScheduledTask();

	/**
	 * Creates the u2k discovery task.
	 * 
	 * @param taskVo
	 *            the task vo
	 * @throws DAOException
	 *             the dAO exception
	 * @throws ResourceException
	 */
	@Override
	public void createU2kDiscoveryTask(ScheduledTaskVo taskVo)
			throws DAOException, ResourceException {

		List<ScheduledTaskVo> discoveryTasks = getAllDiscoveryTasks();

		for (ScheduledTaskVo discoveryTask : discoveryTasks) {
			if (taskVo.equalsTo(discoveryTask)) {
				throw new ResourceException(
						"Scheduled Task with same parameters has already been created");
			}
		}

		MultiTaskScheduler taskScheduler = MultiTaskScheduler.getInstance();
		U2kDiscoveryThread thread = new U2kDiscoveryThread(
				taskVo.getTaskType(), taskVo.getNeId());
		if (!com.fastwire.carriere.common.util.StringUtil.isEmptyString(taskVo
				.getFixedRate())) {

			ScheduledTask scheduledTask = new ScheduledTask(
					taskVo.getTaskType(),

					DateUtil.parseDate(DateUtil.DATE_FULL, taskVo.getEndDate()),
					taskVo.getFixedRateInSec(), taskVo.getDayOfMonth(), taskVo
							.getDayOfWeek(), taskVo.getTimeOfDay(), taskVo
							.getNeId());

			Date startDate = getStartDate(scheduledTask);
			scheduledTask.setStartDate(startDate);

			long delayFromNow = Math.max(0,
					DateUtil.getDiffInSecs(scheduledTask.getStartDate()));

			scheduledTaskDao.saveOrUpdate(scheduledTask);
			taskScheduler.startWithFixedDelay(scheduledTask.getOid(), thread,
					delayFromNow, scheduledTask.getFixedRateInSec());
		} else {
			taskScheduler.startOneshotTask(thread, 0);
		}

	}

	@Override
	public void cancelU2kDiscoveryTask(ScheduledTaskVo taskVo)
			throws DAOException, ResourceException {

		long taskId = Long.parseLong(taskVo.getOid());

		ScheduledTask scheduledTask = scheduledTaskDao
				.getScheduledTaskbyId(taskId);

		if (scheduledTask != null) {
			MultiTaskScheduler taskScheduler = MultiTaskScheduler.getInstance();

			taskScheduler.stopTask(taskId);
			scheduledTaskDao.deleteScheduledTask(scheduledTask);
		} else {
			throw new ResourceException(Messages.getString(
					"message.common.order.scheduledtask.notexistent",
					new String[] { taskVo.getOid() }));
		}
	}

	@Override
	public List<ScheduledTaskVo> getAllDiscoveryTasks() throws DAOException {

		List<ScheduledTask> tasks = scheduledTaskDao
				.getDiscoveryScheduledTasks();

		List<ScheduledTaskVo> taskVos = Lists.newArrayList();

		for (ScheduledTask task : tasks) {
			taskVos.add(new ScheduledTaskVo(task));
		}

		return taskVos;

	}

	@Override
	public void createU2kProvisioningTask(ScheduledTaskVo taskVo)
			throws DAOException {
		MultiTaskScheduler taskScheduler = MultiTaskScheduler.getInstance();
		U2kProvisionThread thread = new U2kProvisionThread();
		if (!com.fastwire.carriere.common.util.StringUtil.isEmptyString(taskVo
				.getFixedRate())) {

			ScheduledTask scheduledTask = new ScheduledTask(
					taskVo.getTaskType(), DateUtil.parseDate(
							DateUtil.DATE_FULL, taskVo.getEndDate()),
					taskVo.getFixedRateInSec(), taskVo.getDayOfMonth(),
					taskVo.getDayOfWeek(), taskVo.getTimeOfDay(),
					taskVo.getNeId());
			Date startDate = getStartDate(scheduledTask);
			scheduledTask.setStartDate(startDate);

			long delayFromNow = Math.max(0,
					DateUtil.getDiffInSecs(scheduledTask.getStartDate()));

			scheduledTaskDao.saveOrUpdate(scheduledTask);
			taskScheduler.startWithFixedDelay(scheduledTask.getOid(), thread,
					delayFromNow, scheduledTask.getFixedRateInSec());
		}

	}

	public static Date getStartDate(ScheduledTask task) {

		Date startDate = DateUtil.getDate();
		String timeOfDay = task.getTimeOfDay();
		Pattern pattern = Pattern.compile("(\\d+):(\\d+)");
		Matcher matcher = pattern.matcher(timeOfDay);
		if (matcher.matches()) {
			int hour = Integer.valueOf(matcher.group(1));
			int minute = Integer.valueOf(matcher.group(2));
			String schedularType = ScheduledTaskConstants.SCHEDULER_TYPE_RATE_MAP
					.inverse().get(task.getFixedRateInSec());

			if (ScheduledTaskConstants.SCHEDULER_TYPE_MONTHLY
					.equals(schedularType)) {
				startDate = DateUtil.getNextValidDate(
						Integer.valueOf(task.getDayOfMonth()) - 1, -1, hour,
						minute);
			} else if (ScheduledTaskConstants.SCHEDULER_TYPE_WEEKLY
					.equals(schedularType)) {

				int dayOfWeek = DateUtil.DAY_OF_WEEK_MAP.get(task
						.getDayOfWeek());
				startDate = DateUtil.getNextValidDate(-1, dayOfWeek, hour,
						minute);
			} else {
				startDate = DateUtil.getNextValidDate(-1, -1, hour, minute);
			}

		}
		return startDate;
	}
	
	
	
	//------------------------------------------------------------------------;
	// added by Jun on 20120501
	public void createRadDiscoveryTask(ScheduledTaskVo taskVo) 
			throws DAOException, ResourceException 
	{
		List<ScheduledTaskVo> discoveryTasks = getAllRadDiscoveryTasks();

		for (ScheduledTaskVo discoveryTask : discoveryTasks) 
		{
			if (taskVo.equalsTo(discoveryTask))
			{
				throw new ResourceException(
						"Scheduled Task with same parameters has already been created");
			}
		}
		
		MultiTaskScheduler taskScheduler = MultiTaskScheduler.getInstance();
		RadDiscoveryThread thread = new RadDiscoveryThread(taskVo.getTaskType(), taskVo.getNeId());
		
		if (!com.fastwire.carriere.common.util.StringUtil.isEmptyString(taskVo.getFixedRate())) 
		{
			ScheduledTask scheduledTask = new ScheduledTask(taskVo.getTaskType(),
					DateUtil.parseDate(DateUtil.DATE_FULL, taskVo.getEndDate()),
					taskVo.getFixedRateInSec(), taskVo.getDayOfMonth(), taskVo
							.getDayOfWeek(), taskVo.getTimeOfDay(), taskVo.getNeId());

			Date startDate = getStartDate(scheduledTask);
			scheduledTask.setStartDate(startDate);

			long delayFromNow = Math.max(0,	DateUtil.getDiffInSecs(scheduledTask.getStartDate()));

			scheduledTaskDao.saveOrUpdate(scheduledTask);
			taskScheduler.startWithFixedDelay(scheduledTask.getOid(), thread,
					delayFromNow, scheduledTask.getFixedRateInSec());
		} 
		else 
		{
			taskScheduler.startOneshotTask(thread, 0);
		}
	}

	// added by Jun on 20120501
    private List<ScheduledTaskVo> getAllRadDiscoveryTasks() throws DAOException
    {
        List<ScheduledTask> tasks = scheduledTaskDao.getRadDiscoveryScheduledTasks();

        List<ScheduledTaskVo> taskVos = Lists.newArrayList();

        for (ScheduledTask task : tasks)
        {
            taskVos.add(new ScheduledTaskVo(task));
        }

        return taskVos;
    }
}
